package com.bnzj.core.persistence.query;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 逻辑表达式
 * @author barry
 * @date 2019-09-29
 */
public class LogicExpression extends AbstractExpression {
    private final BooleanOperator booleanOperator;
    private final List<IExpression> expressions;
    
    public LogicExpression(BooleanOperator booleanOperator, IExpression... expressions) {
        this(booleanOperator, false, expressions);
    }
    
    public LogicExpression(BooleanOperator booleanOperator, boolean negated, IExpression... expressions) {
        super(negated);
        // 1=1
        // 1=1 and 2=2 and 3=3
        // 1=1 or 1=2 or 1=3
        // 1=1 and (1=2 or 3=3)
        // not((1=2 or 3=3) and (1=2 or 1=1))
        if(expressions == null || expressions.length == 0) {
            throw new NullPointerException("expressions is null");
        }
        this.booleanOperator = booleanOperator;
        this.expressions = Arrays.asList(expressions);
    }
    
    public LogicExpression(BooleanOperator booleanOperator, List<IExpression> expressions) {
        this(booleanOperator, false, expressions);
    }
    
    public LogicExpression(BooleanOperator booleanOperator, boolean negated, List<IExpression> expressions) {
        super(negated);
        if(expressions == null || expressions.isEmpty()) {
            throw new NullPointerException("expressions is null");
        }
        this.booleanOperator = booleanOperator;
        this.expressions = expressions;
    }

    @Override
    public BooleanOperator getOperator() {
         return booleanOperator;
    }

    /**
     * @return the expression
     */
    List<IExpression> getExpressions() {
        return expressions;
    }

    /* (non-Javadoc)
     * @see com.bnzj.core.persistence.query.SimpleExpression#buildSQL()
     */
    @Override
    public String buildSQL(Map<String, Object> paramsMap) {
        StringBuilder sql = new StringBuilder();
        int validNumber = 0;
        for (IExpression se : expressions) {
            String tsql = se.buildSQL(paramsMap);
            if (!tsql.isEmpty()) {
                validNumber++;
                sql.append(" ").append(tsql + " " + booleanOperator.name());
            }
        }
        if(sql.length() == 0) {
            return "";
        }
        int index = sql.lastIndexOf(booleanOperator.name());
        if(index > 0) {
            sql.delete(index, index + booleanOperator.name().length());
        }
        if(validNumber > 1) {
            //当子条件多余1个才需要加小括号
            sql.insert(0, "(").append(")");
        }
        if(isNegated()) {
            //当是反条件时，添加not
            sql.insert(0, "(not").append(")");
        }
        return sql.toString();
    }

    @Override
    public IExpression not() {
        return new LogicExpression(booleanOperator, !isNegated(), expressions);
    }
}
